
<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>pymatgen.core.tensors &#8212; pymatgen 2020.7.3 documentation</title>
    <link rel="stylesheet" href="../../../_static/basic.css" type="text/css" />
    <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
    <script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
    <script src="../../../_static/jquery.js"></script>
    <script src="../../../_static/underscore.js"></script>
    <script src="../../../_static/doctools.js"></script>
    <script src="../../../_static/language_data.js"></script>
    <script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
    <link rel="index" title="Index" href="../../../genindex.html" />
    <link rel="search" title="Search" href="../../../search.html" />
 
<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-33990148-1']);
  _gaq.push(['_trackPageview']);
</script>

  </head><body>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="nav-item nav-item-0"><a href="../../../index.html">pymatgen 2020.7.3 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
          <li class="nav-item nav-item-2"><a href="../../pymatgen.html" accesskey="U">pymatgen</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">pymatgen.core.tensors</a></li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
          <div class="body" role="main">
            
  <h1>Source code for pymatgen.core.tensors</h1><div class="highlight"><pre>
<span></span><span class="c1"># coding: utf-8</span>
<span class="c1"># Copyright (c) Pymatgen Development Team.</span>
<span class="c1"># Distributed under the terms of the MIT License.</span>

<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">This module provides a base class for tensor-like objects and methods for</span>
<span class="sd">basic tensor manipulation.  It also provides a class, SquareTensor,</span>
<span class="sd">that provides basic methods for creating and manipulating rank 2 tensors</span>
<span class="sd">&quot;&quot;&quot;</span>

<span class="kn">import</span> <span class="nn">itertools</span>
<span class="kn">import</span> <span class="nn">warnings</span>
<span class="kn">import</span> <span class="nn">collections</span>
<span class="kn">import</span> <span class="nn">string</span>
<span class="kn">import</span> <span class="nn">os</span>

<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>

<span class="kn">from</span> <span class="nn">scipy.linalg</span> <span class="kn">import</span> <span class="n">polar</span>

<span class="kn">from</span> <span class="nn">monty.json</span> <span class="kn">import</span> <span class="n">MSONable</span>
<span class="kn">from</span> <span class="nn">monty.serialization</span> <span class="kn">import</span> <span class="n">loadfn</span>

<span class="kn">from</span> <span class="nn">pymatgen.symmetry.analyzer</span> <span class="kn">import</span> <span class="n">SpacegroupAnalyzer</span>
<span class="kn">from</span> <span class="nn">pymatgen.core.operations</span> <span class="kn">import</span> <span class="n">SymmOp</span>
<span class="kn">from</span> <span class="nn">pymatgen.core.lattice</span> <span class="kn">import</span> <span class="n">Lattice</span>
<span class="kn">from</span> <span class="nn">pymatgen.analysis.structure_matcher</span> <span class="kn">import</span> <span class="n">StructureMatcher</span>

<span class="n">__author__</span> <span class="o">=</span> <span class="s2">&quot;Joseph Montoya&quot;</span>
<span class="n">__copyright__</span> <span class="o">=</span> <span class="s2">&quot;Copyright 2017, The Materials Project&quot;</span>
<span class="n">__credits__</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;Maarten de Jong, Shyam Dwaraknath, Wei Chen, &quot;</span>
               <span class="s2">&quot;Mark Asta, Anubhav Jain, Terence Lew&quot;</span><span class="p">)</span>
<span class="n">__version__</span> <span class="o">=</span> <span class="s2">&quot;1.0&quot;</span>
<span class="n">__maintainer__</span> <span class="o">=</span> <span class="s2">&quot;Joseph Montoya&quot;</span>
<span class="n">__email__</span> <span class="o">=</span> <span class="s2">&quot;montoyjh@lbl.gov&quot;</span>
<span class="n">__status__</span> <span class="o">=</span> <span class="s2">&quot;Production&quot;</span>
<span class="n">__date__</span> <span class="o">=</span> <span class="s2">&quot;July 24, 2018&quot;</span>

<span class="n">voigt_map</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]</span>
<span class="n">reverse_voigt_map</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">4</span><span class="p">],</span>
                              <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span>
                              <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">]])</span>

<span class="n">DEFAULT_QUAD</span> <span class="o">=</span> <span class="n">loadfn</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="vm">__file__</span><span class="p">),</span>
                                   <span class="s2">&quot;quad_data.json&quot;</span><span class="p">))</span>


<div class="viewcode-block" id="Tensor"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor">[docs]</a><span class="k">class</span> <span class="nc">Tensor</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">,</span> <span class="n">MSONable</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Base class for doing useful general operations on Nth order tensors,</span>
<span class="sd">    without restrictions on the type (stress, elastic, strain, piezo, etc.)</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">symbol</span> <span class="o">=</span> <span class="s2">&quot;T&quot;</span>

    <span class="k">def</span> <span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">input_array</span><span class="p">,</span> <span class="n">vscale</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">check_rank</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Create a Tensor object.  Note that the constructor uses __new__</span>
<span class="sd">        rather than __init__ according to the standard method of</span>
<span class="sd">        subclassing numpy ndarrays.</span>

<span class="sd">        Args:</span>
<span class="sd">            input_array: (array-like with shape 3^N): array-like representing</span>
<span class="sd">                a tensor quantity in standard (i. e. non-voigt) notation</span>
<span class="sd">            vscale: (N x M array-like): a matrix corresponding</span>
<span class="sd">                to the coefficients of the voigt-notation tensor</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">obj</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">asarray</span><span class="p">(</span><span class="n">input_array</span><span class="p">)</span><span class="o">.</span><span class="n">view</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span>
        <span class="n">obj</span><span class="o">.</span><span class="n">rank</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">check_rank</span> <span class="ow">and</span> <span class="n">check_rank</span> <span class="o">!=</span> <span class="n">obj</span><span class="o">.</span><span class="n">rank</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">{}</span><span class="s2"> input must be rank </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
                <span class="n">obj</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="n">check_rank</span><span class="p">))</span>

        <span class="n">vshape</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">([</span><span class="mi">3</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">rank</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">rank</span> <span class="o">//</span> <span class="mi">2</span><span class="p">))</span>
        <span class="n">obj</span><span class="o">.</span><span class="n">_vscale</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">ones</span><span class="p">(</span><span class="n">vshape</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">vscale</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
            <span class="n">obj</span><span class="o">.</span><span class="n">_vscale</span> <span class="o">=</span> <span class="n">vscale</span>
        <span class="k">if</span> <span class="n">obj</span><span class="o">.</span><span class="n">_vscale</span><span class="o">.</span><span class="n">shape</span> <span class="o">!=</span> <span class="n">vshape</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Voigt scaling matrix must be the shape of the &quot;</span>
                             <span class="s2">&quot;voigt notation matrix or vector.&quot;</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">all</span><span class="p">([</span><span class="n">i</span> <span class="o">==</span> <span class="mi">3</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">obj</span><span class="o">.</span><span class="n">shape</span><span class="p">]):</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Pymatgen only supports 3-dimensional tensors, &quot;</span>
                             <span class="s2">&quot;and default tensor constructor uses standard &quot;</span>
                             <span class="s2">&quot;notation.  To construct from voigt notation, use&quot;</span>
                             <span class="s2">&quot; </span><span class="si">{}</span><span class="s2">.from_voigt&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">obj</span>

    <span class="k">def</span> <span class="nf">__array_finalize__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="k">return</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">rank</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s1">&#39;rank&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_vscale</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s1">&#39;_vscale&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_vdict</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s1">&#39;_vdict&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__array_wrap__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Overrides __array_wrap__ methods in ndarray superclass to avoid errors</span>
<span class="sd">        associated with functions that return scalar values</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">obj</span><span class="p">[()]</span>
        <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="o">.</span><span class="n">__array_wrap__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">)</span>

    <span class="k">def</span> <span class="fm">__hash__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        define a hash function, since numpy arrays</span>
<span class="sd">        have their own __eq__ method</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="nb">hash</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">tostring</span><span class="p">())</span>

    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s2">&quot;</span><span class="si">{}</span><span class="s2">(</span><span class="si">{}</span><span class="s2">)&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span>
                               <span class="bp">self</span><span class="o">.</span><span class="fm">__str__</span><span class="p">())</span>

<div class="viewcode-block" id="Tensor.zeroed"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.zeroed">[docs]</a>    <span class="k">def</span> <span class="nf">zeroed</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        returns the matrix with all entries below a certain threshold</span>
<span class="sd">        (i.e. tol) set to zero</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">new_tensor</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
        <span class="n">new_tensor</span><span class="p">[</span><span class="nb">abs</span><span class="p">(</span><span class="n">new_tensor</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">tol</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">return</span> <span class="n">new_tensor</span></div>

<div class="viewcode-block" id="Tensor.transform"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.transform">[docs]</a>    <span class="k">def</span> <span class="nf">transform</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">symm_op</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Applies a transformation (via a symmetry operation) to a tensor.</span>

<span class="sd">        Args:</span>
<span class="sd">            symm_op (SymmOp): a symmetry operation to apply to the tensor</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">(</span><span class="n">symm_op</span><span class="o">.</span><span class="n">transform_tensor</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span></div>

<div class="viewcode-block" id="Tensor.rotate"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.rotate">[docs]</a>    <span class="k">def</span> <span class="nf">rotate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">matrix</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Applies a rotation directly, and tests input matrix to ensure a valid</span>
<span class="sd">        rotation.</span>

<span class="sd">        Args:</span>
<span class="sd">            matrix (3x3 array-like): rotation matrix to be applied to tensor</span>
<span class="sd">            tol (float): tolerance for testing rotation matrix validity</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">matrix</span> <span class="o">=</span> <span class="n">SquareTensor</span><span class="p">(</span><span class="n">matrix</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">matrix</span><span class="o">.</span><span class="n">is_rotation</span><span class="p">(</span><span class="n">tol</span><span class="p">):</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Rotation matrix is not valid.&quot;</span><span class="p">)</span>
        <span class="n">sop</span> <span class="o">=</span> <span class="n">SymmOp</span><span class="o">.</span><span class="n">from_rotation_and_translation</span><span class="p">(</span><span class="n">matrix</span><span class="p">,</span>
                                                   <span class="p">[</span><span class="mf">0.</span><span class="p">,</span> <span class="mf">0.</span><span class="p">,</span> <span class="mf">0.</span><span class="p">])</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span><span class="n">sop</span><span class="p">)</span></div>

<div class="viewcode-block" id="Tensor.einsum_sequence"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.einsum_sequence">[docs]</a>    <span class="k">def</span> <span class="nf">einsum_sequence</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other_arrays</span><span class="p">,</span> <span class="n">einsum_string</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Calculates the result of an einstein summation expression</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other_arrays</span><span class="p">,</span> <span class="nb">list</span><span class="p">):</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;other tensors must be list of &quot;</span>
                             <span class="s2">&quot;tensors or tensor input&quot;</span><span class="p">)</span>

        <span class="n">other_arrays</span> <span class="o">=</span> <span class="p">[</span><span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">other_arrays</span><span class="p">]</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">einsum_string</span><span class="p">:</span>
            <span class="n">lc</span> <span class="o">=</span> <span class="n">string</span><span class="o">.</span><span class="n">ascii_lowercase</span>
            <span class="n">einsum_string</span> <span class="o">=</span> <span class="n">lc</span><span class="p">[:</span><span class="bp">self</span><span class="o">.</span><span class="n">rank</span><span class="p">]</span>
            <span class="n">other_ranks</span> <span class="o">=</span> <span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">other_arrays</span><span class="p">]</span>
            <span class="n">idx</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rank</span> <span class="o">-</span> <span class="nb">sum</span><span class="p">(</span><span class="n">other_ranks</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">length</span> <span class="ow">in</span> <span class="n">other_ranks</span><span class="p">:</span>
                <span class="n">einsum_string</span> <span class="o">+=</span> <span class="s1">&#39;,&#39;</span> <span class="o">+</span> <span class="n">lc</span><span class="p">[</span><span class="n">idx</span><span class="p">:</span><span class="n">idx</span> <span class="o">+</span> <span class="n">length</span><span class="p">]</span>
                <span class="n">idx</span> <span class="o">+=</span> <span class="n">length</span>

        <span class="n">einsum_args</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="p">]</span> <span class="o">+</span> <span class="nb">list</span><span class="p">(</span><span class="n">other_arrays</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">einsum</span><span class="p">(</span><span class="n">einsum_string</span><span class="p">,</span> <span class="o">*</span><span class="n">einsum_args</span><span class="p">)</span></div>

<div class="viewcode-block" id="Tensor.project"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.project">[docs]</a>    <span class="k">def</span> <span class="nf">project</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Convenience method for projection of a tensor into a</span>
<span class="sd">        vector.  Returns the tensor dotted into a unit vector</span>
<span class="sd">        along the input n.</span>

<span class="sd">        Args:</span>
<span class="sd">            n (3x1 array-like): direction to project onto</span>

<span class="sd">        Returns (float):</span>
<span class="sd">            scalar value corresponding to the projection of</span>
<span class="sd">            the tensor into the vector</span>

<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">n</span> <span class="o">=</span> <span class="n">get_uvec</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">einsum_sequence</span><span class="p">([</span><span class="n">n</span><span class="p">]</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">rank</span><span class="p">)</span></div>

<div class="viewcode-block" id="Tensor.average_over_unit_sphere"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.average_over_unit_sphere">[docs]</a>    <span class="k">def</span> <span class="nf">average_over_unit_sphere</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">quad</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Method for averaging the tensor projection over the unit</span>
<span class="sd">        with option for custom quadrature.</span>

<span class="sd">        Args:</span>
<span class="sd">            quad (dict): quadrature for integration, should be</span>
<span class="sd">                dictionary with &quot;points&quot; and &quot;weights&quot; keys defaults</span>
<span class="sd">                to quadpy.sphere.Lebedev(19) as read from file</span>

<span class="sd">        Returns:</span>
<span class="sd">            Average of tensor projected into vectors on the unit sphere</span>

<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">quad</span> <span class="o">=</span> <span class="n">quad</span> <span class="ow">or</span> <span class="n">DEFAULT_QUAD</span>
        <span class="n">weights</span><span class="p">,</span> <span class="n">points</span> <span class="o">=</span> <span class="n">quad</span><span class="p">[</span><span class="s1">&#39;weights&#39;</span><span class="p">],</span> <span class="n">quad</span><span class="p">[</span><span class="s1">&#39;points&#39;</span><span class="p">]</span>
        <span class="k">return</span> <span class="nb">sum</span><span class="p">([</span><span class="n">w</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">project</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="k">for</span> <span class="n">w</span><span class="p">,</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">weights</span><span class="p">,</span> <span class="n">points</span><span class="p">)])</span></div>

<div class="viewcode-block" id="Tensor.get_grouped_indices"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.get_grouped_indices">[docs]</a>    <span class="k">def</span> <span class="nf">get_grouped_indices</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">voigt</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Gets index sets for equivalent tensor values</span>

<span class="sd">        Args:</span>
<span class="sd">            voigt (bool): whether to get grouped indices</span>
<span class="sd">                of voigt or full notation tensor, defaults</span>
<span class="sd">                to false</span>
<span class="sd">            **kwargs: keyword args for np.isclose.  Can take atol</span>
<span class="sd">                and rtol for absolute and relative tolerance, e. g.</span>

<span class="sd">                &gt;&gt;&gt; tensor.group_array_indices(atol=1e-8)</span>

<span class="sd">                or</span>

<span class="sd">                &gt;&gt;&gt; tensor.group_array_indices(rtol=1e-5)</span>

<span class="sd">        Returns:</span>
<span class="sd">            list of index groups where tensor values are equivalent to</span>
<span class="sd">            within tolerances</span>

<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">voigt</span><span class="p">:</span>
            <span class="n">array</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">voigt</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">array</span> <span class="o">=</span> <span class="bp">self</span>

        <span class="n">indices</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="o">*</span><span class="p">[</span><span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">array</span><span class="o">.</span><span class="n">shape</span><span class="p">]))</span>
        <span class="n">remaining</span> <span class="o">=</span> <span class="n">indices</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
        <span class="c1"># Start with everything near zero</span>
        <span class="n">grouped</span> <span class="o">=</span> <span class="p">[</span><span class="nb">list</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">isclose</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">))))]</span>
        <span class="n">remaining</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">remaining</span> <span class="k">if</span> <span class="n">i</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">grouped</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
        <span class="c1"># Iteratively run through remaining indices</span>
        <span class="k">while</span> <span class="n">remaining</span><span class="p">:</span>
            <span class="n">new</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">np</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">isclose</span><span class="p">(</span>
                <span class="n">array</span><span class="p">,</span> <span class="n">array</span><span class="p">[</span><span class="n">remaining</span><span class="p">[</span><span class="mi">0</span><span class="p">]],</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">))))</span>
            <span class="n">grouped</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">new</span><span class="p">)</span>
            <span class="n">remaining</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">remaining</span> <span class="k">if</span> <span class="n">i</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">new</span><span class="p">]</span>
        <span class="c1"># Don&#39;t return any empty lists</span>
        <span class="k">return</span> <span class="p">[</span><span class="n">g</span> <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">grouped</span> <span class="k">if</span> <span class="n">g</span><span class="p">]</span></div>

<div class="viewcode-block" id="Tensor.get_symbol_dict"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.get_symbol_dict">[docs]</a>    <span class="k">def</span> <span class="nf">get_symbol_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">voigt</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">zero_index</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Creates a summary dict for tensor with associated symbol</span>

<span class="sd">        Args:</span>
<span class="sd">            voigt (bool): whether to get symbol dict for voigt</span>
<span class="sd">                notation tensor, as opposed to full notation,</span>
<span class="sd">                defaults to true</span>
<span class="sd">            zero_index (bool): whether to set initial index to zero,</span>
<span class="sd">                defaults to false, since tensor notations tend to use</span>
<span class="sd">                one-indexing, rather than zero indexing like python</span>
<span class="sd">            **kwargs: keyword args for np.isclose.  Can take atol</span>
<span class="sd">                and rtol for absolute and relative tolerance, e. g.</span>

<span class="sd">                &gt;&gt;&gt; tensor.get_symbol_dict(atol=1e-8)</span>

<span class="sd">                or</span>

<span class="sd">                &gt;&gt;&gt; tensor.get_symbol_dict(rtol=1e-5)</span>

<span class="sd">        Returns:</span>
<span class="sd">            list of index groups where tensor values are equivalent to</span>
<span class="sd">            within tolerances</span>

<span class="sd">        Returns:</span>

<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">d</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">if</span> <span class="n">voigt</span><span class="p">:</span>
            <span class="n">array</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">voigt</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">array</span> <span class="o">=</span> <span class="bp">self</span>
        <span class="n">grouped</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_grouped_indices</span><span class="p">(</span><span class="n">voigt</span><span class="o">=</span><span class="n">voigt</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">zero_index</span><span class="p">:</span>
            <span class="n">p</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">p</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="k">for</span> <span class="n">indices</span> <span class="ow">in</span> <span class="n">grouped</span><span class="p">:</span>
            <span class="n">sym_string</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">symbol</span> <span class="o">+</span> <span class="s1">&#39;_&#39;</span>
            <span class="n">sym_string</span> <span class="o">+=</span> <span class="s1">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">p</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">indices</span><span class="p">[</span><span class="mi">0</span><span class="p">]])</span>
            <span class="n">value</span> <span class="o">=</span> <span class="n">array</span><span class="p">[</span><span class="n">indices</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">np</span><span class="o">.</span><span class="n">isclose</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span>
                <span class="n">d</span><span class="p">[</span><span class="n">sym_string</span><span class="p">]</span> <span class="o">=</span> <span class="n">array</span><span class="p">[</span><span class="n">indices</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
        <span class="k">return</span> <span class="n">d</span></div>

<div class="viewcode-block" id="Tensor.round"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.round">[docs]</a>    <span class="k">def</span> <span class="nf">round</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">decimals</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Wrapper around numpy.round to ensure object</span>
<span class="sd">        of same type is returned</span>

<span class="sd">        Args:</span>
<span class="sd">            decimals :Number of decimal places to round to (default: 0).</span>
<span class="sd">                If decimals is negative, it specifies the number of</span>
<span class="sd">                positions to the left of the decimal point.</span>

<span class="sd">        Returns (Tensor):</span>
<span class="sd">            rounded tensor of same type</span>

<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">round</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">decimals</span><span class="o">=</span><span class="n">decimals</span><span class="p">))</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">symmetrized</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns a generally symmetrized tensor, calculated by taking</span>
<span class="sd">        the sum of the tensor and its transpose with respect to all</span>
<span class="sd">        possible permutations of indices</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">perms</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">permutations</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rank</span><span class="p">)))</span>
        <span class="k">return</span> <span class="nb">sum</span><span class="p">([</span><span class="n">np</span><span class="o">.</span><span class="n">transpose</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ind</span><span class="p">)</span> <span class="k">for</span> <span class="n">ind</span> <span class="ow">in</span> <span class="n">perms</span><span class="p">])</span> <span class="o">/</span> <span class="nb">len</span><span class="p">(</span><span class="n">perms</span><span class="p">)</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">voigt_symmetrized</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns a &quot;voigt&quot;-symmetrized tensor, i. e. a voigt-notation</span>
<span class="sd">        tensor such that it is invariant wrt permutation of indices</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rank</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">rank</span> <span class="o">&gt;=</span> <span class="mi">2</span><span class="p">):</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;V-symmetrization requires rank even and &gt;= 2&quot;</span><span class="p">)</span>

        <span class="n">v</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">voigt</span>
        <span class="n">perms</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">permutations</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">v</span><span class="o">.</span><span class="n">shape</span><span class="p">))))</span>
        <span class="n">new_v</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">([</span><span class="n">np</span><span class="o">.</span><span class="n">transpose</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">ind</span><span class="p">)</span> <span class="k">for</span> <span class="n">ind</span> <span class="ow">in</span> <span class="n">perms</span><span class="p">])</span> <span class="o">/</span> <span class="nb">len</span><span class="p">(</span><span class="n">perms</span><span class="p">)</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="n">from_voigt</span><span class="p">(</span><span class="n">new_v</span><span class="p">)</span>

<div class="viewcode-block" id="Tensor.is_symmetric"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.is_symmetric">[docs]</a>    <span class="k">def</span> <span class="nf">is_symmetric</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-5</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Tests whether a tensor is symmetric or not based on the residual</span>
<span class="sd">        with its symmetric part, from self.symmetrized</span>

<span class="sd">        Args:</span>
<span class="sd">            tol (float): tolerance to test for symmetry</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="p">(</span><span class="bp">self</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">symmetrized</span> <span class="o">&lt;</span> <span class="n">tol</span><span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span></div>

<div class="viewcode-block" id="Tensor.fit_to_structure"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.fit_to_structure">[docs]</a>    <span class="k">def</span> <span class="nf">fit_to_structure</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">symprec</span><span class="o">=</span><span class="mf">0.1</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns a tensor that is invariant with respect to symmetry</span>
<span class="sd">        operations corresponding to a structure</span>

<span class="sd">        Args:</span>
<span class="sd">            structure (Structure): structure from which to generate</span>
<span class="sd">                symmetry operations</span>
<span class="sd">            symprec (float): symmetry tolerance for the Spacegroup Analyzer</span>
<span class="sd">                used to generate the symmetry operations</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">sga</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">symprec</span><span class="p">)</span>
        <span class="n">symm_ops</span> <span class="o">=</span> <span class="n">sga</span><span class="o">.</span><span class="n">get_symmetry_operations</span><span class="p">(</span><span class="n">cartesian</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
        <span class="k">return</span> <span class="nb">sum</span><span class="p">([</span><span class="bp">self</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span><span class="n">symm_op</span><span class="p">)</span>
                    <span class="k">for</span> <span class="n">symm_op</span> <span class="ow">in</span> <span class="n">symm_ops</span><span class="p">])</span> <span class="o">/</span> <span class="nb">len</span><span class="p">(</span><span class="n">symm_ops</span><span class="p">)</span></div>

<div class="viewcode-block" id="Tensor.is_fit_to_structure"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.is_fit_to_structure">[docs]</a>    <span class="k">def</span> <span class="nf">is_fit_to_structure</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-2</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Tests whether a tensor is invariant with respect to the</span>
<span class="sd">        symmetry operations of a particular structure by testing</span>
<span class="sd">        whether the residual of the symmetric portion is below a</span>
<span class="sd">        tolerance</span>

<span class="sd">        Args:</span>
<span class="sd">            structure (Structure): structure to be fit to</span>
<span class="sd">            tol (float): tolerance for symmetry testing</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="p">(</span><span class="bp">self</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">fit_to_structure</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">tol</span><span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">voigt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns the tensor in Voigt notation</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">v_matrix</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_vscale</span><span class="o">.</span><span class="n">shape</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">dtype</span><span class="p">)</span>
        <span class="n">this_voigt_map</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_voigt_dict</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rank</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">ind</span> <span class="ow">in</span> <span class="n">this_voigt_map</span><span class="p">:</span>
            <span class="n">v_matrix</span><span class="p">[</span><span class="n">this_voigt_map</span><span class="p">[</span><span class="n">ind</span><span class="p">]]</span> <span class="o">=</span> <span class="bp">self</span><span class="p">[</span><span class="n">ind</span><span class="p">]</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_voigt_symmetric</span><span class="p">():</span>
            <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">&quot;Tensor is not symmetric, information may &quot;</span>
                          <span class="s2">&quot;be lost in voigt conversion.&quot;</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">v_matrix</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">_vscale</span>

<div class="viewcode-block" id="Tensor.is_voigt_symmetric"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.is_voigt_symmetric">[docs]</a>    <span class="k">def</span> <span class="nf">is_voigt_symmetric</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-6</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Tests symmetry of tensor to that necessary for voigt-conversion</span>
<span class="sd">        by grouping indices into pairs and constructing a sequence of</span>
<span class="sd">        possible permutations to be used in a tensor transpose</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">transpose_pieces</span> <span class="o">=</span> <span class="p">[[[</span><span class="mi">0</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rank</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)]]]</span>
        <span class="n">transpose_pieces</span> <span class="o">+=</span> <span class="p">[[</span><span class="nb">range</span><span class="p">(</span><span class="n">j</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)]</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span>
                             <span class="nb">range</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rank</span> <span class="o">%</span> <span class="mi">2</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rank</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
        <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rank</span> <span class="o">%</span> <span class="mi">2</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">transpose_pieces</span><span class="p">)):</span>
            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">transpose_pieces</span><span class="p">[</span><span class="n">n</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
                <span class="n">transpose_pieces</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">+=</span> <span class="p">[</span><span class="n">transpose_pieces</span><span class="p">[</span><span class="n">n</span><span class="p">][</span><span class="mi">0</span><span class="p">][::</span><span class="o">-</span><span class="mi">1</span><span class="p">]]</span>
        <span class="k">for</span> <span class="n">trans_seq</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="o">*</span><span class="n">transpose_pieces</span><span class="p">):</span>
            <span class="n">trans_seq</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">(</span><span class="o">*</span><span class="n">trans_seq</span><span class="p">))</span>
            <span class="k">if</span> <span class="p">(</span><span class="bp">self</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">transpose</span><span class="p">(</span><span class="n">trans_seq</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">tol</span><span class="p">)</span><span class="o">.</span><span class="n">any</span><span class="p">():</span>
                <span class="k">return</span> <span class="kc">False</span>
        <span class="k">return</span> <span class="kc">True</span></div>

<div class="viewcode-block" id="Tensor.get_voigt_dict"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.get_voigt_dict">[docs]</a>    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">get_voigt_dict</span><span class="p">(</span><span class="n">rank</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns a dictionary that maps indices in the tensor to those</span>
<span class="sd">        in a voigt representation based on input rank</span>

<span class="sd">        Args:</span>
<span class="sd">            rank (int): Tensor rank to generate the voigt map</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">vdict</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">for</span> <span class="n">ind</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="o">*</span><span class="p">[</span><span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">)]</span> <span class="o">*</span> <span class="n">rank</span><span class="p">):</span>
            <span class="n">v_ind</span> <span class="o">=</span> <span class="n">ind</span><span class="p">[:</span><span class="n">rank</span> <span class="o">%</span> <span class="mi">2</span><span class="p">]</span>
            <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">rank</span> <span class="o">//</span> <span class="mi">2</span><span class="p">):</span>
                <span class="n">pos</span> <span class="o">=</span> <span class="n">rank</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">j</span>
                <span class="n">v_ind</span> <span class="o">+=</span> <span class="p">(</span><span class="n">reverse_voigt_map</span><span class="p">[</span><span class="n">ind</span><span class="p">[</span><span class="n">pos</span><span class="p">:</span><span class="n">pos</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]],)</span>
            <span class="n">vdict</span><span class="p">[</span><span class="n">ind</span><span class="p">]</span> <span class="o">=</span> <span class="n">v_ind</span>
        <span class="k">return</span> <span class="n">vdict</span></div>

<div class="viewcode-block" id="Tensor.from_voigt"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.from_voigt">[docs]</a>    <span class="nd">@classmethod</span>
    <span class="k">def</span> <span class="nf">from_voigt</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">voigt_input</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Constructor based on the voigt notation vector or matrix.</span>

<span class="sd">        Args:</span>
<span class="sd">            voigt_input (array-like): voigt input for a given tensor</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">voigt_input</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">voigt_input</span><span class="p">)</span>
        <span class="n">rank</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">voigt_input</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span> <span class="o">//</span> <span class="mi">3</span>
        <span class="n">t</span> <span class="o">=</span> <span class="bp">cls</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">([</span><span class="mi">3</span><span class="p">]</span> <span class="o">*</span> <span class="n">rank</span><span class="p">))</span>
        <span class="k">if</span> <span class="n">voigt_input</span><span class="o">.</span><span class="n">shape</span> <span class="o">!=</span> <span class="n">t</span><span class="o">.</span><span class="n">_vscale</span><span class="o">.</span><span class="n">shape</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Invalid shape for voigt matrix&quot;</span><span class="p">)</span>
        <span class="n">voigt_input</span> <span class="o">=</span> <span class="n">voigt_input</span> <span class="o">/</span> <span class="n">t</span><span class="o">.</span><span class="n">_vscale</span>
        <span class="n">this_voigt_map</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">get_voigt_dict</span><span class="p">(</span><span class="n">rank</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">ind</span> <span class="ow">in</span> <span class="n">this_voigt_map</span><span class="p">:</span>
            <span class="n">t</span><span class="p">[</span><span class="n">ind</span><span class="p">]</span> <span class="o">=</span> <span class="n">voigt_input</span><span class="p">[</span><span class="n">this_voigt_map</span><span class="p">[</span><span class="n">ind</span><span class="p">]]</span>
        <span class="k">return</span> <span class="bp">cls</span><span class="p">(</span><span class="n">t</span><span class="p">)</span></div>

<div class="viewcode-block" id="Tensor.get_ieee_rotation"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.get_ieee_rotation">[docs]</a>    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">get_ieee_rotation</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">refine_rotation</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Given a structure associated with a tensor, determines</span>
<span class="sd">        the rotation matrix for IEEE conversion according to</span>
<span class="sd">        the 1987 IEEE standards.</span>

<span class="sd">        Args:</span>
<span class="sd">            structure (Structure): a structure associated with the</span>
<span class="sd">                tensor to be converted to the IEEE standard</span>
<span class="sd">            refine_rotation (bool): whether to refine the rotation</span>
<span class="sd">                using SquareTensor.refine_rotation</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c1"># Check conventional setting:</span>
        <span class="n">sga</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
        <span class="n">dataset</span> <span class="o">=</span> <span class="n">sga</span><span class="o">.</span><span class="n">get_symmetry_dataset</span><span class="p">()</span>
        <span class="n">trans_mat</span> <span class="o">=</span> <span class="n">dataset</span><span class="p">[</span><span class="s1">&#39;transformation_matrix&#39;</span><span class="p">]</span>
        <span class="n">conv_latt</span> <span class="o">=</span> <span class="n">Lattice</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">transpose</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">dot</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">transpose</span><span class="p">(</span>
            <span class="n">structure</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">matrix</span><span class="p">),</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">inv</span><span class="p">(</span><span class="n">trans_mat</span><span class="p">))))</span>
        <span class="n">xtal_sys</span> <span class="o">=</span> <span class="n">sga</span><span class="o">.</span><span class="n">get_crystal_system</span><span class="p">()</span>

        <span class="n">vecs</span> <span class="o">=</span> <span class="n">conv_latt</span><span class="o">.</span><span class="n">matrix</span>
        <span class="n">lengths</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">conv_latt</span><span class="o">.</span><span class="n">abc</span><span class="p">)</span>
        <span class="n">angles</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">conv_latt</span><span class="o">.</span><span class="n">angles</span><span class="p">)</span>
        <span class="n">rotation</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">((</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>

        <span class="c1"># IEEE rules: a,b,c || x1,x2,x3</span>
        <span class="k">if</span> <span class="n">xtal_sys</span> <span class="o">==</span> <span class="s2">&quot;cubic&quot;</span><span class="p">:</span>
            <span class="n">rotation</span> <span class="o">=</span> <span class="p">[</span><span class="n">vecs</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">/</span> <span class="n">lengths</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">)]</span>

        <span class="c1"># IEEE rules: a=b in length; c,a || x3, x1</span>
        <span class="k">elif</span> <span class="n">xtal_sys</span> <span class="o">==</span> <span class="s2">&quot;tetragonal&quot;</span><span class="p">:</span>
            <span class="n">rotation</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="n">vec</span> <span class="o">/</span> <span class="n">mag</span> <span class="k">for</span> <span class="p">(</span><span class="n">mag</span><span class="p">,</span> <span class="n">vec</span><span class="p">)</span> <span class="ow">in</span>
                                 <span class="nb">sorted</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">lengths</span><span class="p">,</span> <span class="n">vecs</span><span class="p">),</span>
                                        <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">])])</span>
            <span class="k">if</span> <span class="nb">abs</span><span class="p">(</span><span class="n">lengths</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">-</span> <span class="n">lengths</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">&lt;</span> <span class="nb">abs</span><span class="p">(</span><span class="n">lengths</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">lengths</span><span class="p">[</span><span class="mi">0</span><span class="p">]):</span>
                <span class="n">rotation</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">rotation</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">rotation</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">rotation</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
            <span class="n">rotation</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">get_uvec</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">cross</span><span class="p">(</span><span class="n">rotation</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">rotation</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>

        <span class="c1"># IEEE rules: c&lt;a&lt;b; c,a || x3,x1</span>
        <span class="k">elif</span> <span class="n">xtal_sys</span> <span class="o">==</span> <span class="s2">&quot;orthorhombic&quot;</span><span class="p">:</span>
            <span class="n">rotation</span> <span class="o">=</span> <span class="p">[</span><span class="n">vec</span> <span class="o">/</span> <span class="n">mag</span> <span class="k">for</span> <span class="p">(</span><span class="n">mag</span><span class="p">,</span> <span class="n">vec</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">lengths</span><span class="p">,</span> <span class="n">vecs</span><span class="p">))]</span>
            <span class="n">rotation</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">roll</span><span class="p">(</span><span class="n">rotation</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>

        <span class="c1"># IEEE rules: c,a || x3,x1, c is threefold axis</span>
        <span class="c1"># Note this also includes rhombohedral crystal systems</span>
        <span class="k">elif</span> <span class="n">xtal_sys</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">&quot;trigonal&quot;</span><span class="p">,</span> <span class="s2">&quot;hexagonal&quot;</span><span class="p">):</span>
            <span class="c1"># find threefold axis:</span>
            <span class="n">tf_index</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">argmin</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">angles</span> <span class="o">-</span> <span class="mf">120.</span><span class="p">))</span>
            <span class="n">non_tf_mask</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">logical_not</span><span class="p">(</span><span class="n">angles</span> <span class="o">==</span> <span class="n">angles</span><span class="p">[</span><span class="n">tf_index</span><span class="p">])</span>
            <span class="n">rotation</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">get_uvec</span><span class="p">(</span><span class="n">vecs</span><span class="p">[</span><span class="n">tf_index</span><span class="p">])</span>
            <span class="n">rotation</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">get_uvec</span><span class="p">(</span><span class="n">vecs</span><span class="p">[</span><span class="n">non_tf_mask</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
            <span class="n">rotation</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">get_uvec</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">cross</span><span class="p">(</span><span class="n">rotation</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">rotation</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>

        <span class="c1"># IEEE rules: b,c || x2,x3; alpha=beta=90, c&lt;a</span>
        <span class="k">elif</span> <span class="n">xtal_sys</span> <span class="o">==</span> <span class="s2">&quot;monoclinic&quot;</span><span class="p">:</span>
            <span class="c1"># Find unique axis</span>
            <span class="n">u_index</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">argmax</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">angles</span> <span class="o">-</span> <span class="mf">90.</span><span class="p">))</span>
            <span class="n">n_umask</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">logical_not</span><span class="p">(</span><span class="n">angles</span> <span class="o">==</span> <span class="n">angles</span><span class="p">[</span><span class="n">u_index</span><span class="p">])</span>
            <span class="n">rotation</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">get_uvec</span><span class="p">(</span><span class="n">vecs</span><span class="p">[</span><span class="n">u_index</span><span class="p">])</span>
            <span class="c1"># Shorter of remaining lattice vectors for c axis</span>
            <span class="n">c</span> <span class="o">=</span> <span class="p">[</span><span class="n">vec</span> <span class="o">/</span> <span class="n">mag</span> <span class="k">for</span> <span class="p">(</span><span class="n">mag</span><span class="p">,</span> <span class="n">vec</span><span class="p">)</span> <span class="ow">in</span>
                 <span class="nb">sorted</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">lengths</span><span class="p">[</span><span class="n">n_umask</span><span class="p">],</span> <span class="n">vecs</span><span class="p">[</span><span class="n">n_umask</span><span class="p">]))][</span><span class="mi">0</span><span class="p">]</span>
            <span class="n">rotation</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
            <span class="n">rotation</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">cross</span><span class="p">(</span><span class="n">rotation</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">rotation</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>

        <span class="c1"># IEEE rules: c || x3, x2 normal to ac plane</span>
        <span class="k">elif</span> <span class="n">xtal_sys</span> <span class="o">==</span> <span class="s2">&quot;triclinic&quot;</span><span class="p">:</span>
            <span class="n">rotation</span> <span class="o">=</span> <span class="p">[</span><span class="n">vec</span> <span class="o">/</span> <span class="n">mag</span> <span class="k">for</span> <span class="p">(</span><span class="n">mag</span><span class="p">,</span> <span class="n">vec</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">lengths</span><span class="p">,</span> <span class="n">vecs</span><span class="p">))]</span>
            <span class="n">rotation</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">get_uvec</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">cross</span><span class="p">(</span><span class="n">rotation</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">rotation</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
            <span class="n">rotation</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">cross</span><span class="p">(</span><span class="n">rotation</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">rotation</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>

        <span class="n">rotation</span> <span class="o">=</span> <span class="n">SquareTensor</span><span class="p">(</span><span class="n">rotation</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">refine_rotation</span><span class="p">:</span>
            <span class="n">rotation</span> <span class="o">=</span> <span class="n">rotation</span><span class="o">.</span><span class="n">refine_rotation</span><span class="p">()</span>

        <span class="k">return</span> <span class="n">rotation</span></div>

<div class="viewcode-block" id="Tensor.convert_to_ieee"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.convert_to_ieee">[docs]</a>    <span class="k">def</span> <span class="nf">convert_to_ieee</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">initial_fit</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
                        <span class="n">refine_rotation</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Given a structure associated with a tensor, attempts a</span>
<span class="sd">        calculation of the tensor in IEEE format according to</span>
<span class="sd">        the 1987 IEEE standards.</span>

<span class="sd">        Args:</span>
<span class="sd">            structure (Structure): a structure associated with the</span>
<span class="sd">                tensor to be converted to the IEEE standard</span>
<span class="sd">            initial_fit (bool): flag to indicate whether initial</span>
<span class="sd">                tensor is fit to the symmetry of the structure.</span>
<span class="sd">                Defaults to true. Note that if false, inconsistent</span>
<span class="sd">                results may be obtained due to symmetrically</span>
<span class="sd">                equivalent, but distinct transformations</span>
<span class="sd">                being used in different versions of spglib.</span>
<span class="sd">            refine_rotation (bool): whether to refine the rotation</span>
<span class="sd">                produced by the ieee transform generator, default True</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">rotation</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_ieee_rotation</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">refine_rotation</span><span class="p">)</span>
        <span class="n">result</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
        <span class="k">if</span> <span class="n">initial_fit</span><span class="p">:</span>
            <span class="n">result</span> <span class="o">=</span> <span class="n">result</span><span class="o">.</span><span class="n">fit_to_structure</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">result</span><span class="o">.</span><span class="n">rotate</span><span class="p">(</span><span class="n">rotation</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-2</span><span class="p">)</span></div>

<div class="viewcode-block" id="Tensor.structure_transform"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.structure_transform">[docs]</a>    <span class="k">def</span> <span class="nf">structure_transform</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">original_structure</span><span class="p">,</span> <span class="n">new_structure</span><span class="p">,</span>
                            <span class="n">refine_rotation</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Transforms a tensor from one basis for an original structure</span>
<span class="sd">        into a new basis defined by a new structure.</span>

<span class="sd">        Args:</span>
<span class="sd">            original_structure (Structure): structure corresponding</span>
<span class="sd">                to the basis of the current tensor</span>
<span class="sd">            new_structure (Structure): structure corresponding to the</span>
<span class="sd">                desired basis</span>
<span class="sd">            refine_rotation (bool): whether to refine the rotations</span>
<span class="sd">                generated in get_ieee_rotation</span>

<span class="sd">        Returns:</span>
<span class="sd">            Tensor that has been transformed such that its basis</span>
<span class="sd">            corresponds to the new_structure&#39;s basis</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">sm</span> <span class="o">=</span> <span class="n">StructureMatcher</span><span class="p">()</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">sm</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="n">original_structure</span><span class="p">,</span> <span class="n">new_structure</span><span class="p">):</span>
            <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">&quot;original and new structures do not match!&quot;</span><span class="p">)</span>
        <span class="n">trans_1</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_ieee_rotation</span><span class="p">(</span><span class="n">original_structure</span><span class="p">,</span> <span class="n">refine_rotation</span><span class="p">)</span>
        <span class="n">trans_2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_ieee_rotation</span><span class="p">(</span><span class="n">new_structure</span><span class="p">,</span> <span class="n">refine_rotation</span><span class="p">)</span>
        <span class="c1"># Get the ieee format tensor</span>
        <span class="n">new</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rotate</span><span class="p">(</span><span class="n">trans_1</span><span class="p">)</span>
        <span class="c1"># Reverse the ieee format rotation for the second structure</span>
        <span class="n">new</span> <span class="o">=</span> <span class="n">new</span><span class="o">.</span><span class="n">rotate</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">transpose</span><span class="p">(</span><span class="n">trans_2</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">new</span></div>

<div class="viewcode-block" id="Tensor.from_values_indices"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.from_values_indices">[docs]</a>    <span class="nd">@classmethod</span>
    <span class="k">def</span> <span class="nf">from_values_indices</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">indices</span><span class="p">,</span> <span class="n">populate</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
                            <span class="n">structure</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">voigt_rank</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
                            <span class="n">vsym</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Creates a tensor from values and indices, with options</span>
<span class="sd">        for populating the remainder of the tensor.</span>

<span class="sd">        Args:</span>
<span class="sd">            values (floats): numbers to place at indices</span>
<span class="sd">            indices (array-likes): indices to place values at</span>
<span class="sd">            populate (bool): whether to populate the tensor</span>
<span class="sd">            structure (Structure): structure to base population</span>
<span class="sd">                or fit_to_structure on</span>
<span class="sd">            voigt_rank (int): full tensor rank to indicate the</span>
<span class="sd">                shape of the resulting tensor.  This is necessary</span>
<span class="sd">                if one provides a set of indices more minimal than</span>
<span class="sd">                the shape of the tensor they want, e.g.</span>
<span class="sd">                Tensor.from_values_indices((0, 0), 100)</span>
<span class="sd">            vsym (bool): whether to voigt symmetrize during the</span>
<span class="sd">                optimization procedure</span>
<span class="sd">            verbose (bool): whether to populate verbosely</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c1"># auto-detect voigt notation</span>
        <span class="c1"># TODO: refactor rank inheritance to make this easier</span>
        <span class="n">indices</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">indices</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">voigt_rank</span><span class="p">:</span>
            <span class="n">shape</span> <span class="o">=</span> <span class="p">([</span><span class="mi">3</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">voigt_rank</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">voigt_rank</span> <span class="o">//</span> <span class="mi">2</span><span class="p">))</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">shape</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">max</span><span class="p">(</span><span class="n">indices</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> <span class="o">/</span> <span class="mf">3.</span><span class="p">)</span> <span class="o">*</span> <span class="mi">3</span>
        <span class="n">base</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">(</span><span class="n">shape</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">int</span><span class="p">))</span>
        <span class="k">for</span> <span class="n">v</span><span class="p">,</span> <span class="n">idx</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">indices</span><span class="p">):</span>
            <span class="n">base</span><span class="p">[</span><span class="nb">tuple</span><span class="p">(</span><span class="n">idx</span><span class="p">)]</span> <span class="o">=</span> <span class="n">v</span>
        <span class="k">if</span> <span class="mi">6</span> <span class="ow">in</span> <span class="n">shape</span><span class="p">:</span>
            <span class="n">obj</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">from_voigt</span><span class="p">(</span><span class="n">base</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">obj</span> <span class="o">=</span> <span class="bp">cls</span><span class="p">(</span><span class="n">base</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">populate</span><span class="p">:</span>
            <span class="k">assert</span> <span class="n">structure</span><span class="p">,</span> <span class="s2">&quot;Populate option must include structure input&quot;</span>
            <span class="n">obj</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">populate</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">vsym</span><span class="o">=</span><span class="n">vsym</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="n">verbose</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">structure</span><span class="p">:</span>
            <span class="n">obj</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">fit_to_structure</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">obj</span></div>

<div class="viewcode-block" id="Tensor.populate"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.populate">[docs]</a>    <span class="k">def</span> <span class="nf">populate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">prec</span><span class="o">=</span><span class="mf">1e-5</span><span class="p">,</span> <span class="n">maxiter</span><span class="o">=</span><span class="mi">200</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
                 <span class="n">precond</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">vsym</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Takes a partially populated tensor, and populates the non-zero</span>
<span class="sd">        entries according to the following procedure, iterated until</span>
<span class="sd">        the desired convergence (specified via prec) is achieved.</span>

<span class="sd">        1. Find non-zero entries</span>
<span class="sd">        2. Symmetrize the tensor with respect to crystal symmetry and</span>
<span class="sd">           (optionally) voigt symmetry</span>
<span class="sd">        3. Reset the non-zero entries of the original tensor</span>

<span class="sd">        Args:</span>
<span class="sd">            structure (structure object)</span>
<span class="sd">            prec (float): precision for determining a non-zero value</span>
<span class="sd">            maxiter (int): maximum iterations for populating the tensor</span>
<span class="sd">            verbose (bool): whether to populate verbosely</span>
<span class="sd">            precond (bool): whether to precondition by cycling through</span>
<span class="sd">                all symmops and storing new nonzero values, default True</span>
<span class="sd">            vsym (bool): whether to enforce voigt symmetry, defaults</span>
<span class="sd">                to True</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">precond</span><span class="p">:</span>
            <span class="c1"># Generate the guess from populated</span>
            <span class="n">sops</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span><span class="o">.</span><span class="n">get_symmetry_operations</span><span class="p">()</span>
            <span class="n">guess</span> <span class="o">=</span> <span class="n">Tensor</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">shape</span><span class="p">))</span>
            <span class="n">mask</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">prec</span>
            <span class="n">guess</span><span class="p">[</span><span class="n">mask</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="p">[</span><span class="n">mask</span><span class="p">]</span>

            <span class="k">def</span> <span class="nf">merge</span><span class="p">(</span><span class="n">old</span><span class="p">,</span> <span class="n">new</span><span class="p">):</span>
                <span class="n">gmask</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">old</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">prec</span>
                <span class="n">nmask</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">new</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">prec</span>
                <span class="n">new_mask</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">logical_not</span><span class="p">(</span><span class="n">gmask</span><span class="p">)</span> <span class="o">*</span> <span class="n">nmask</span>
                <span class="n">avg_mask</span> <span class="o">=</span> <span class="n">gmask</span> <span class="o">*</span> <span class="n">nmask</span>
                <span class="n">old</span><span class="p">[</span><span class="n">avg_mask</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">old</span><span class="p">[</span><span class="n">avg_mask</span><span class="p">]</span> <span class="o">+</span> <span class="n">new</span><span class="p">[</span><span class="n">avg_mask</span><span class="p">])</span> <span class="o">/</span> <span class="mf">2.</span>
                <span class="n">old</span><span class="p">[</span><span class="n">new_mask</span><span class="p">]</span> <span class="o">=</span> <span class="n">new</span><span class="p">[</span><span class="n">new_mask</span><span class="p">]</span>

            <span class="k">if</span> <span class="n">verbose</span><span class="p">:</span>
                <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Preconditioning for </span><span class="si">{}</span><span class="s2"> symmops&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sops</span><span class="p">)))</span>
            <span class="k">for</span> <span class="n">sop</span> <span class="ow">in</span> <span class="n">sops</span><span class="p">:</span>
                <span class="n">rot</span> <span class="o">=</span> <span class="n">guess</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span><span class="n">sop</span><span class="p">)</span>
                <span class="c1"># Store non-zero entries of new that weren&#39;t previously</span>
                <span class="c1"># in the guess in the guess</span>
                <span class="n">merge</span><span class="p">(</span><span class="n">guess</span><span class="p">,</span> <span class="n">rot</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">verbose</span><span class="p">:</span>
                <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Preconditioning for voigt symmetry&quot;</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">vsym</span><span class="p">:</span>
                <span class="n">v</span> <span class="o">=</span> <span class="n">guess</span><span class="o">.</span><span class="n">voigt</span>
                <span class="n">perms</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">permutations</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">v</span><span class="o">.</span><span class="n">shape</span><span class="p">))))</span>
                <span class="k">for</span> <span class="n">perm</span> <span class="ow">in</span> <span class="n">perms</span><span class="p">:</span>
                    <span class="n">vtrans</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">transpose</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">perm</span><span class="p">)</span>
                    <span class="n">merge</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">vtrans</span><span class="p">)</span>
                <span class="n">guess</span> <span class="o">=</span> <span class="n">Tensor</span><span class="o">.</span><span class="n">from_voigt</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">guess</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span>

        <span class="k">assert</span> <span class="n">guess</span><span class="o">.</span><span class="n">shape</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">shape</span><span class="p">,</span> <span class="s2">&quot;Guess must have same shape&quot;</span>
        <span class="n">converged</span> <span class="o">=</span> <span class="kc">False</span>
        <span class="n">test_new</span><span class="p">,</span> <span class="n">test_old</span> <span class="o">=</span> <span class="p">[</span><span class="n">guess</span><span class="o">.</span><span class="n">copy</span><span class="p">()]</span> <span class="o">*</span> <span class="mi">2</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">maxiter</span><span class="p">):</span>
            <span class="n">test_new</span> <span class="o">=</span> <span class="n">test_old</span><span class="o">.</span><span class="n">fit_to_structure</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">vsym</span><span class="p">:</span>
                <span class="n">test_new</span> <span class="o">=</span> <span class="n">test_new</span><span class="o">.</span><span class="n">voigt_symmetrized</span>
            <span class="n">diff</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">test_old</span> <span class="o">-</span> <span class="n">test_new</span><span class="p">)</span>
            <span class="n">converged</span> <span class="o">=</span> <span class="p">(</span><span class="n">diff</span> <span class="o">&lt;</span> <span class="n">prec</span><span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
            <span class="k">if</span> <span class="n">converged</span><span class="p">:</span>
                <span class="k">break</span>
            <span class="n">test_new</span><span class="p">[</span><span class="n">mask</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="p">[</span><span class="n">mask</span><span class="p">]</span>
            <span class="n">test_old</span> <span class="o">=</span> <span class="n">test_new</span>
            <span class="k">if</span> <span class="n">verbose</span><span class="p">:</span>
                <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Iteration </span><span class="si">{}</span><span class="s2">: </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">np</span><span class="o">.</span><span class="n">max</span><span class="p">(</span><span class="n">diff</span><span class="p">)))</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">converged</span><span class="p">:</span>
            <span class="n">max_diff</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">max</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="bp">self</span> <span class="o">-</span> <span class="n">test_new</span><span class="p">))</span>
            <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">&quot;Warning, populated tensor is not converged &quot;</span>
                          <span class="s2">&quot;with max diff of </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">max_diff</span><span class="p">))</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">(</span><span class="n">test_new</span><span class="p">)</span></div>

<div class="viewcode-block" id="Tensor.as_dict"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.as_dict">[docs]</a>    <span class="k">def</span> <span class="nf">as_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">voigt</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Serializes the tensor object</span>

<span class="sd">        Args:</span>
<span class="sd">            voigt (bool): flag for whether to store entries in</span>
<span class="sd">                voigt-notation.  Defaults to false, as information</span>
<span class="sd">                may be lost in conversion.</span>

<span class="sd">        Returns (Dict):</span>
<span class="sd">            serialized format tensor object</span>

<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">input_array</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">voigt</span> <span class="k">if</span> <span class="n">voigt</span> <span class="k">else</span> <span class="bp">self</span>
        <span class="n">d</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;@module&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__module__</span><span class="p">,</span>
             <span class="s2">&quot;@class&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span>
             <span class="s2">&quot;input_array&quot;</span><span class="p">:</span> <span class="n">input_array</span><span class="o">.</span><span class="n">tolist</span><span class="p">()}</span>
        <span class="k">if</span> <span class="n">voigt</span><span class="p">:</span>
            <span class="n">d</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">&quot;voigt&quot;</span><span class="p">:</span> <span class="n">voigt</span><span class="p">})</span>
        <span class="k">return</span> <span class="n">d</span></div>

<div class="viewcode-block" id="Tensor.from_dict"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.Tensor.from_dict">[docs]</a>    <span class="nd">@classmethod</span>
    <span class="k">def</span> <span class="nf">from_dict</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;MSONAble from_dict implementation.&quot;&quot;&quot;</span>
        <span class="n">voigt</span> <span class="o">=</span> <span class="n">d</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;voigt&#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">voigt</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">cls</span><span class="o">.</span><span class="n">from_voigt</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;input_array&quot;</span><span class="p">])</span>
        <span class="k">return</span> <span class="bp">cls</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;input_array&quot;</span><span class="p">])</span></div></div>


<div class="viewcode-block" id="TensorCollection"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection">[docs]</a><span class="k">class</span> <span class="nc">TensorCollection</span><span class="p">(</span><span class="n">collections</span><span class="o">.</span><span class="n">abc</span><span class="o">.</span><span class="n">Sequence</span><span class="p">,</span> <span class="n">MSONable</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A sequence of tensors that can be used for fitting data</span>
<span class="sd">    or for having a tensor expansion</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tensor_list</span><span class="p">,</span> <span class="n">base_class</span><span class="o">=</span><span class="n">Tensor</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param tensor_list: List of tensors.</span>
<span class="sd">        :param base_class: Class to be used.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tensors</span> <span class="o">=</span> <span class="p">[</span><span class="n">base_class</span><span class="p">(</span><span class="n">t</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">base_class</span><span class="p">)</span>
                        <span class="k">else</span> <span class="n">t</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">tensor_list</span><span class="p">]</span>

    <span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">tensors</span><span class="p">)</span>

    <span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ind</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">tensors</span><span class="p">[</span><span class="n">ind</span><span class="p">]</span>

    <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">tensors</span><span class="o">.</span><span class="fm">__iter__</span><span class="p">()</span>

<div class="viewcode-block" id="TensorCollection.zeroed"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.zeroed">[docs]</a>    <span class="k">def</span> <span class="nf">zeroed</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param tol: Tolerance</span>
<span class="sd">        :return: TensorCollection where small values are set to 0.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">([</span><span class="n">t</span><span class="o">.</span><span class="n">zeroed</span><span class="p">(</span><span class="n">tol</span><span class="p">)</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">])</span></div>

<div class="viewcode-block" id="TensorCollection.transform"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.transform">[docs]</a>    <span class="k">def</span> <span class="nf">transform</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">symm_op</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Transforms TensorCollection with a symmetry operation.</span>

<span class="sd">        :param symm_op: SymmetryOperation.</span>
<span class="sd">        :return: TensorCollection.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">([</span><span class="n">t</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span><span class="n">symm_op</span><span class="p">)</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">])</span></div>

<div class="viewcode-block" id="TensorCollection.rotate"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.rotate">[docs]</a>    <span class="k">def</span> <span class="nf">rotate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">matrix</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Rotates TensorCollection.</span>

<span class="sd">        :param matrix: Rotation matrix.</span>
<span class="sd">        :param tol: tolerance.</span>
<span class="sd">        :return: TensorCollection.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">([</span><span class="n">t</span><span class="o">.</span><span class="n">rotate</span><span class="p">(</span><span class="n">matrix</span><span class="p">,</span> <span class="n">tol</span><span class="p">)</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">])</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">symmetrized</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :return: TensorCollection where all tensors are symmetrized.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">([</span><span class="n">t</span><span class="o">.</span><span class="n">symmetrized</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">])</span>

<div class="viewcode-block" id="TensorCollection.is_symmetric"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.is_symmetric">[docs]</a>    <span class="k">def</span> <span class="nf">is_symmetric</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-5</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param tol: tolerance</span>
<span class="sd">        :return: Whether all tensors are symmetric.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="nb">all</span><span class="p">([</span><span class="n">t</span><span class="o">.</span><span class="n">is_symmetric</span><span class="p">(</span><span class="n">tol</span><span class="p">)</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">])</span></div>

<div class="viewcode-block" id="TensorCollection.fit_to_structure"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.fit_to_structure">[docs]</a>    <span class="k">def</span> <span class="nf">fit_to_structure</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">symprec</span><span class="o">=</span><span class="mf">0.1</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Fits all tensors to a Structure.</span>

<span class="sd">        :param structure: Structure</span>
<span class="sd">        :param symprec: symmetry precision.</span>
<span class="sd">        :return: TensorCollection.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">([</span><span class="n">t</span><span class="o">.</span><span class="n">fit_to_structure</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">symprec</span><span class="p">)</span>
                               <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">])</span></div>

<div class="viewcode-block" id="TensorCollection.is_fit_to_structure"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.is_fit_to_structure">[docs]</a>    <span class="k">def</span> <span class="nf">is_fit_to_structure</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-2</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param structure: Structure</span>
<span class="sd">        :param tol: tolerance</span>
<span class="sd">        :return: Whether all tensors are fitted to Structure.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="nb">all</span><span class="p">([</span><span class="n">t</span><span class="o">.</span><span class="n">is_fit_to_structure</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">tol</span><span class="p">)</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">])</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">voigt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :return: TensorCollection where all tensors are in voight form.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">voigt</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">]</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">ranks</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :return: Ranks for all tensors.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">rank</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">]</span>

<div class="viewcode-block" id="TensorCollection.is_voigt_symmetric"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.is_voigt_symmetric">[docs]</a>    <span class="k">def</span> <span class="nf">is_voigt_symmetric</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-6</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param tol: tolerance</span>
<span class="sd">        :return: Whether all tensors are voigt symmetric.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="nb">all</span><span class="p">([</span><span class="n">t</span><span class="o">.</span><span class="n">is_voigt_symmetric</span><span class="p">(</span><span class="n">tol</span><span class="p">)</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">])</span></div>

<div class="viewcode-block" id="TensorCollection.from_voigt"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.from_voigt">[docs]</a>    <span class="nd">@classmethod</span>
    <span class="k">def</span> <span class="nf">from_voigt</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">voigt_input_list</span><span class="p">,</span> <span class="n">base_class</span><span class="o">=</span><span class="n">Tensor</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Creates TensorCollection from voigt form.</span>

<span class="sd">        :param voigt_input_list: List of voigt tensors</span>
<span class="sd">        :param base_class: Class for tensor.</span>
<span class="sd">        :return: TensorCollection.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">cls</span><span class="p">([</span><span class="n">base_class</span><span class="o">.</span><span class="n">from_voigt</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">voigt_input_list</span><span class="p">])</span></div>

<div class="viewcode-block" id="TensorCollection.convert_to_ieee"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.convert_to_ieee">[docs]</a>    <span class="k">def</span> <span class="nf">convert_to_ieee</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">initial_fit</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
                        <span class="n">refine_rotation</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Convert all tensors to IEEE.</span>

<span class="sd">        :param structure: Structure</span>
<span class="sd">        :param initial_fit: Whether to perform an initial fit.</span>
<span class="sd">        :param refine_rotation: Whether to refine the rotation.</span>
<span class="sd">        :return: TensorCollection.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">(</span>
            <span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">convert_to_ieee</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">initial_fit</span><span class="p">,</span> <span class="n">refine_rotation</span><span class="p">)</span>
             <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">])</span></div>

<div class="viewcode-block" id="TensorCollection.round"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.round">[docs]</a>    <span class="k">def</span> <span class="nf">round</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Round all tensors.</span>

<span class="sd">        :param args: Passthrough to Tensor.round</span>
<span class="sd">        :param kwargs: Passthrough to Tensor.round</span>
<span class="sd">        :return: TensorCollection.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">([</span><span class="n">t</span><span class="o">.</span><span class="n">round</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">])</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">voigt_symmetrized</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :return: TensorCollection where all tensors are voigt symmetrized.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">([</span><span class="n">t</span><span class="o">.</span><span class="n">voigt_symmetrized</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">])</span>

<div class="viewcode-block" id="TensorCollection.as_dict"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.as_dict">[docs]</a>    <span class="k">def</span> <span class="nf">as_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">voigt</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param voigt: Whether to use voight form.</span>
<span class="sd">        :return: Dict representation of TensorCollection.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">tensor_list</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">voigt</span> <span class="k">if</span> <span class="n">voigt</span> <span class="k">else</span> <span class="bp">self</span>
        <span class="n">d</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;@module&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__module__</span><span class="p">,</span>
             <span class="s2">&quot;@class&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span>
             <span class="s2">&quot;tensor_list&quot;</span><span class="p">:</span> <span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">tolist</span><span class="p">()</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">tensor_list</span><span class="p">]}</span>
        <span class="k">if</span> <span class="n">voigt</span><span class="p">:</span>
            <span class="n">d</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">&quot;voigt&quot;</span><span class="p">:</span> <span class="n">voigt</span><span class="p">})</span>
        <span class="k">return</span> <span class="n">d</span></div>

<div class="viewcode-block" id="TensorCollection.from_dict"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorCollection.from_dict">[docs]</a>    <span class="nd">@classmethod</span>
    <span class="k">def</span> <span class="nf">from_dict</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Creates TensorCollection from dict.</span>

<span class="sd">        :param d: dict</span>
<span class="sd">        :return: TensorCollection</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">voigt</span> <span class="o">=</span> <span class="n">d</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;voigt&#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">voigt</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">cls</span><span class="o">.</span><span class="n">from_voigt</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;tensor_list&quot;</span><span class="p">])</span>
        <span class="k">return</span> <span class="bp">cls</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;tensor_list&quot;</span><span class="p">])</span></div></div>


<div class="viewcode-block" id="SquareTensor"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.SquareTensor">[docs]</a><span class="k">class</span> <span class="nc">SquareTensor</span><span class="p">(</span><span class="n">Tensor</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Base class for doing useful general operations on second rank tensors</span>
<span class="sd">    (stress, strain etc.).</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">input_array</span><span class="p">,</span> <span class="n">vscale</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Create a SquareTensor object.  Note that the constructor uses __new__</span>
<span class="sd">        rather than __init__ according to the standard method of</span>
<span class="sd">        subclassing numpy ndarrays.  Error is thrown when the class is</span>
<span class="sd">        initialized with non-square matrix.</span>

<span class="sd">        Args:</span>
<span class="sd">            input_array (3x3 array-like): the 3x3 array-like</span>
<span class="sd">                representing the content of the tensor</span>
<span class="sd">            vscale (6x1 array-like): 6x1 array-like scaling the</span>
<span class="sd">                voigt-notation vector with the tensor entries</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">obj</span> <span class="o">=</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">input_array</span><span class="p">,</span> <span class="n">vscale</span><span class="p">,</span>
                              <span class="n">check_rank</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">obj</span><span class="o">.</span><span class="n">view</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">trans</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        shorthand for transpose on SquareTensor</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="n">SquareTensor</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">transpose</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inv</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        shorthand for matrix inverse on SquareTensor</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">det</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;SquareTensor is non-invertible&quot;</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">SquareTensor</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">inv</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">det</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        shorthand for the determinant of the SquareTensor</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">det</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>

<div class="viewcode-block" id="SquareTensor.is_rotation"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.SquareTensor.is_rotation">[docs]</a>    <span class="k">def</span> <span class="nf">is_rotation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">,</span> <span class="n">include_improper</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Test to see if tensor is a valid rotation matrix, performs a</span>
<span class="sd">        test to check whether the inverse is equal to the transpose</span>
<span class="sd">        and if the determinant is equal to one within the specified</span>
<span class="sd">        tolerance</span>

<span class="sd">        Args:</span>
<span class="sd">            tol (float): tolerance to both tests of whether the</span>
<span class="sd">                the determinant is one and the inverse is equal</span>
<span class="sd">                to the transpose</span>
<span class="sd">            include_improper (bool): whether to include improper</span>
<span class="sd">                rotations in the determination of validity</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">det</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">det</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
        <span class="k">if</span> <span class="n">include_improper</span><span class="p">:</span>
            <span class="n">det</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">det</span><span class="p">)</span>
        <span class="k">return</span> <span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">inv</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">trans</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">tol</span><span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span> <span class="ow">and</span> <span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">det</span> <span class="o">-</span> <span class="mf">1.</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">tol</span><span class="p">)</span></div>

<div class="viewcode-block" id="SquareTensor.refine_rotation"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.SquareTensor.refine_rotation">[docs]</a>    <span class="k">def</span> <span class="nf">refine_rotation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Helper method for refining rotation matrix by ensuring</span>
<span class="sd">        that second and third rows are perpindicular to the first.</span>
<span class="sd">        Gets new y vector from an orthogonal projection of x onto y</span>
<span class="sd">        and the new z vector from a cross product of the new x and y</span>

<span class="sd">        Args:</span>
<span class="sd">            tol to test for rotation</span>

<span class="sd">        Returns:</span>
<span class="sd">            new rotation matrix</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">new_x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">get_uvec</span><span class="p">(</span><span class="bp">self</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="n">get_uvec</span><span class="p">(</span><span class="bp">self</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
        <span class="c1"># Get a projection on y</span>
        <span class="n">new_y</span> <span class="o">=</span> <span class="n">y</span> <span class="o">-</span> <span class="n">np</span><span class="o">.</span><span class="n">dot</span><span class="p">(</span><span class="n">new_x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="o">*</span> <span class="n">new_x</span>
        <span class="n">new_z</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">cross</span><span class="p">(</span><span class="n">new_x</span><span class="p">,</span> <span class="n">new_y</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">SquareTensor</span><span class="p">([</span><span class="n">new_x</span><span class="p">,</span> <span class="n">new_y</span><span class="p">,</span> <span class="n">new_z</span><span class="p">])</span></div>

<div class="viewcode-block" id="SquareTensor.get_scaled"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.SquareTensor.get_scaled">[docs]</a>    <span class="k">def</span> <span class="nf">get_scaled</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">scale_factor</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Scales the tensor by a certain multiplicative scale factor</span>

<span class="sd">        Args:</span>
<span class="sd">            scale_factor (float): scalar multiplier to be applied to the</span>
<span class="sd">                SquareTensor object</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="n">SquareTensor</span><span class="p">(</span><span class="bp">self</span> <span class="o">*</span> <span class="n">scale_factor</span><span class="p">)</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">principal_invariants</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns a list of principal invariants for the tensor,</span>
<span class="sd">        which are the values of the coefficients of the characteristic</span>
<span class="sd">        polynomial for the matrix</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">poly</span><span class="p">(</span><span class="bp">self</span><span class="p">)[</span><span class="mi">1</span><span class="p">:]</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">])</span>

<div class="viewcode-block" id="SquareTensor.polar_decomposition"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.SquareTensor.polar_decomposition">[docs]</a>    <span class="k">def</span> <span class="nf">polar_decomposition</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">side</span><span class="o">=</span><span class="s1">&#39;right&#39;</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        calculates matrices for polar decomposition</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="n">polar</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">side</span><span class="o">=</span><span class="n">side</span><span class="p">)</span></div></div>


<div class="viewcode-block" id="get_uvec"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.get_uvec">[docs]</a><span class="k">def</span> <span class="nf">get_uvec</span><span class="p">(</span><span class="n">vec</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; Gets a unit vector parallel to input vector&quot;&quot;&quot;</span>
    <span class="n">l</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="n">vec</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">l</span> <span class="o">&lt;</span> <span class="mf">1e-8</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">vec</span>
    <span class="k">return</span> <span class="n">vec</span> <span class="o">/</span> <span class="n">l</span></div>


<div class="viewcode-block" id="symmetry_reduce"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.symmetry_reduce">[docs]</a><span class="k">def</span> <span class="nf">symmetry_reduce</span><span class="p">(</span><span class="n">tensors</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-8</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Function that converts a list of tensors corresponding to a structure</span>
<span class="sd">    and returns a dictionary consisting of unique tensor keys with symmop</span>
<span class="sd">    values corresponding to transformations that will result in derivative</span>
<span class="sd">    tensors from the original list</span>

<span class="sd">    Args:</span>
<span class="sd">        tensors (list of tensors): list of Tensor objects to test for</span>
<span class="sd">            symmetrically-equivalent duplicates</span>
<span class="sd">        structure (Structure): structure from which to get symmetry</span>
<span class="sd">        tol (float): tolerance for tensor equivalence</span>
<span class="sd">        kwargs: keyword arguments for the SpacegroupAnalyzer</span>

<span class="sd">    returns:</span>
<span class="sd">        dictionary consisting of unique tensors with symmetry operations</span>
<span class="sd">        corresponding to those which will reconstruct the remaining</span>
<span class="sd">        tensors as values</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">sga</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
    <span class="n">symmops</span> <span class="o">=</span> <span class="n">sga</span><span class="o">.</span><span class="n">get_symmetry_operations</span><span class="p">(</span><span class="n">cartesian</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
    <span class="n">unique_mapping</span> <span class="o">=</span> <span class="n">TensorMapping</span><span class="p">([</span><span class="n">tensors</span><span class="p">[</span><span class="mi">0</span><span class="p">]],</span> <span class="p">[[]],</span> <span class="n">tol</span><span class="o">=</span><span class="n">tol</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">tensor</span> <span class="ow">in</span> <span class="n">tensors</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
        <span class="n">is_unique</span> <span class="o">=</span> <span class="kc">True</span>
        <span class="k">for</span> <span class="n">unique_tensor</span><span class="p">,</span> <span class="n">symmop</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="n">unique_mapping</span><span class="p">,</span> <span class="n">symmops</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">np</span><span class="o">.</span><span class="n">allclose</span><span class="p">(</span><span class="n">unique_tensor</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span><span class="n">symmop</span><span class="p">),</span> <span class="n">tensor</span><span class="p">,</span> <span class="n">atol</span><span class="o">=</span><span class="n">tol</span><span class="p">):</span>
                <span class="n">unique_mapping</span><span class="p">[</span><span class="n">unique_tensor</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">symmop</span><span class="p">)</span>
                <span class="n">is_unique</span> <span class="o">=</span> <span class="kc">False</span>
                <span class="k">break</span>
        <span class="k">if</span> <span class="n">is_unique</span><span class="p">:</span>
            <span class="n">unique_mapping</span><span class="p">[</span><span class="n">tensor</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">return</span> <span class="n">unique_mapping</span></div>


<div class="viewcode-block" id="TensorMapping"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorMapping">[docs]</a><span class="k">class</span> <span class="nc">TensorMapping</span><span class="p">(</span><span class="n">collections</span><span class="o">.</span><span class="n">abc</span><span class="o">.</span><span class="n">MutableMapping</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Base class for tensor mappings, which function much like</span>
<span class="sd">    a dictionary, but use numpy routines to determine approximate</span>
<span class="sd">    equality to keys for getting and setting items.</span>

<span class="sd">    This is intended primarily for convenience with things like</span>
<span class="sd">    stress-strain pairs and fitting data manipulation.  In general,</span>
<span class="sd">    it is significantly less robust than a typical hashing</span>
<span class="sd">    and should be used with care.</span>

<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tensors</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">values</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-5</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Initialize a TensorMapping</span>

<span class="sd">        Args:</span>
<span class="sd">            tensor_list ([Tensor]): list of tensors</span>
<span class="sd">            value_list ([]): list of values to be associated with tensors</span>
<span class="sd">            tol (float): an absolute tolerance for getting and setting</span>
<span class="sd">                items in the mapping</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_tensor_list</span> <span class="o">=</span> <span class="n">tensors</span> <span class="ow">or</span> <span class="p">[]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_value_list</span> <span class="o">=</span> <span class="n">values</span> <span class="ow">or</span> <span class="p">[]</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_tensor_list</span><span class="p">)</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_value_list</span><span class="p">):</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;TensorMapping must be initialized with tensors&quot;</span>
                             <span class="s2">&quot;and values of equivalent length&quot;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tol</span> <span class="o">=</span> <span class="n">tol</span>

    <span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span>
        <span class="n">index</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_item_index</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">index</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">KeyError</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">{}</span><span class="s2"> not found in mapping.&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">item</span><span class="p">))</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_value_list</span><span class="p">[</span><span class="n">index</span><span class="p">]</span>

    <span class="k">def</span> <span class="fm">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="n">index</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_item_index</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">index</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_tensor_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_value_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_value_list</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>

    <span class="k">def</span> <span class="fm">__delitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
        <span class="n">index</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_item_index</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_tensor_list</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">index</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_value_list</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">index</span><span class="p">)</span>

    <span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_tensor_list</span><span class="p">)</span>

    <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_tensor_list</span><span class="p">:</span>
            <span class="k">yield</span> <span class="n">item</span>

<div class="viewcode-block" id="TensorMapping.values"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorMapping.values">[docs]</a>    <span class="k">def</span> <span class="nf">values</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :return: Values in mapping.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_value_list</span></div>

<div class="viewcode-block" id="TensorMapping.items"><a class="viewcode-back" href="../../../pymatgen.core.tensors.html#pymatgen.core.tensors.TensorMapping.items">[docs]</a>    <span class="k">def</span> <span class="nf">items</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :return: Items in mapping.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="nb">zip</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_tensor_list</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_value_list</span><span class="p">)</span></div>

    <span class="k">def</span> <span class="fm">__contains__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span>
        <span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_item_index</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span>

    <span class="k">def</span> <span class="nf">_get_item_index</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_tensor_list</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="kc">None</span>
        <span class="n">item</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
        <span class="n">axis</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
        <span class="n">mask</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">all</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_tensor_list</span><span class="p">)</span> <span class="o">-</span> <span class="n">item</span><span class="p">)</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">tol</span><span class="p">,</span>
                      <span class="n">axis</span><span class="o">=</span><span class="n">axis</span><span class="p">)</span>
        <span class="n">indices</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">mask</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">indices</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Tensor key collision.&quot;</span><span class="p">)</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">indices</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="kc">None</span>
        <span class="k">return</span> <span class="n">indices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></div>
</pre></div>

            <div class="clearer"></div>
          </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="nav-item nav-item-0"><a href="../../../index.html">pymatgen 2020.7.3 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
          <li class="nav-item nav-item-2"><a href="../../pymatgen.html" >pymatgen</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">pymatgen.core.tensors</a></li> 
      </ul>
    </div>

    <div class="footer" role="contentinfo">
        &#169; Copyright 2011, Pymatgen Development Team.
      Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.2.
    </div>
<div class="footer">This page uses <a href="http://analytics.google.com/">
Google Analytics</a> to collect statistics. You can disable it by blocking
the JavaScript coming from www.google-analytics.com.
<script type="text/javascript">
  (function() {
    var ga = document.createElement('script');
    ga.src = ('https:' == document.location.protocol ?
              'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    ga.setAttribute('async', 'true');
    document.documentElement.firstChild.appendChild(ga);
  })();
</script>
</div>

  </body>
</html>